
import 'dart:convert';

import 'package:im_app/im/util/MapUtil.dart';
import 'package:logger/logger.dart';
import 'package:sqflite/sqflite.dart';

import '../pojo/ImPojo.dart';
import '../socket/dto/business/PullData.dart';
import '../util/DateUtil.dart';
import '../util/ImSingleton.dart';
import 'BaseDao.dart';

class ImUserDao extends BaseDao {

  final _logger = Logger(
    printer: PrettyPrinter(),
  );

  Future<ImUser?> getByUserId(String userId) async {
    Database? database = getDatabase(); //await getReadOnlyDatabase(); //ImSingleton.getInstance()?.dataBase;
    List? list = await database?.rawQuery("select * from im_user where userId = ?", [userId]);
    if (list != null && list.isNotEmpty) {
      return Future.value(_toImUser(list[0]));
    }
    return Future.value(null);
  }

  Future<List<ImUser>> getUsers(int size) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    List<Map<String, Object?>>? list = await database?.query("im_user", orderBy: 'firstLetter', limit: size);
    return list != null ? list.map((map)=>_toImUser(map)).toList() : [];
  }

  Future<List<ImUser>> getNewByStartId(int start, int size) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    List<Map<String, Object?>>? list = await database?.query("im_user",
        orderBy: 'firstLetter asc, id asc', offset: start, limit: size);
    return list != null ? list.map((map)=>_toImUser(map)).toList() : [];
  }

  Future<List<ImUser>> getUsersByUserIds(List<String> codeList) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    String param = codeList.map((e) => "\"$e\"").join(",");
    String sql = "select * from im_user where userId in ($param)";
    List<Map<String, Object?>>? list = await database?.rawQuery(sql, []);
    return Future.value(list?.map((map)=>_toImUser(map)).toList());
  }

  Future<List<ImUser>> getByDepartmentId(String departmentCode, int start, int pageSize) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    String sql = "select * from im_user where departmentCode = ? order by id limit ?, ?";
    List<Map<String, Object?>>? list = await database?.rawQuery(sql, [departmentCode, start, pageSize]);
    return Future.value(list?.map((map)=>_toImUser(map)).toList());
  }

  Future<void> batchInserts(List<ImUser> imUsers) async {
    Database? database = ImSingleton.getInstance().dataBase;
    Batch? batch = database?.batch();
    for (var user in imUsers) {
      var data = _toInsertValueMap(user);
      batch?.insert("im_user", data);
    }
    List<Object?>? list = await batch?.commit();
    _logger.i("batch insertUsers json: " + jsonEncode(list));
  }

  Future<void> batchUpdates(List<ImUser> imUsers) async {
    Database? database = getDatabase(); //ImSingleton.getInstance()?.dataBase;
    Batch? batch = database?.batch();
    for (var user in imUsers) {
      var data = _toInsertValueMap(user);
      batch?.update("im_user", data, where: "userId=?", whereArgs:[user.userId]);
    }
    List<Object?>? list = await batch?.commit();
    _logger.i("batch updateUsers json: " + jsonEncode(list));
  }

  Map<String, Object?> _toInsertValueMap(ImUser imUser) {
    Map<String, Object?> map = {};
    map['userId'] = imUser.userId;
    map["status"]= imUser.status?.value;
    map['userName'] = imUser.userName;
    map['mobile'] = imUser.mobile;
    map['motto'] = imUser.motto;
    map['sex'] = imUser.sex?.value;
    map['departmentCode'] = imUser.departmentCode;
    map['otherDepartmentCodes'] = imUser.otherDepartmentCodes;
    map['ext1'] = imUser.ext1;
    map['ext2'] = imUser.ext2;
    map['firstLetter'] = imUser.firstLetter;
    map['createTime'] = DateUtil.formatDate(imUser.createTime);
    map['updateTime'] = DateUtil.formatDate(imUser.updateTime);

    return map;
  }

  ImUser _toImUser(Map<String, dynamic> map) {
    var user = ImUser(MapUtil.getString(map, "userId"));
    user.id = MapUtil.getInt(map, "id");
    user.userName = MapUtil.getStringOrNull(map, "userName");
    user.mobile = MapUtil.getStringOrNull(map, "mobile");
    user.motto = MapUtil.getStringOrNull(map, "motto");
    user.description = MapUtil.getStringOrNull(map, "description");
    user.headImg = MapUtil.getStringOrNull(map, "headImg");
    user.status = ImUserStatus.ofValue(MapUtil.getInt(map, "status"));
    user.sex = SexEnum.ofValue(MapUtil.getIntOrNull(map, "sex"));
    user.departmentCode = MapUtil.getStringOrNull(map, "departmentCode");
    user.otherDepartmentCodes = MapUtil.getStringOrNull(map, "otherDepartmentCodes");
    user.ext1 = MapUtil.getStringOrNull(map, "ext1");
    user.ext2 = MapUtil.getStringOrNull(map, "ext2");
    user.firstLetter = MapUtil.getStringOrNull(map, "firstLetter");
    user.createTime = MapUtil.getDate(map, 'createTime');
    user.updateTime =  MapUtil.getDate(map, 'updateTime');
    return user;
  }
}